{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Writing functions and for-loops using Python\n",
    "\n",
    "Author: <a href=\"mailto:a.owen@leeds.ac.uk\"> Dr Anne Owen </a> \n",
    "\n",
    "Before we start, paste the following into the box below:\n",
    "\n",
    "```python\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "%config InteractiveShell.ast_node_interactivity='last_expr_or_assign'\n",
    "%precision 2\n",
    "pd.options.display.precision = 2\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. Functions\n",
    "\n",
    "In the previous exercise we wrote commands to python line-by-line.\n",
    "\n",
    "In this exercise we are going to group the commands together into a function.\n",
    "\n",
    "A function is a block of code which only runs when it is called. You can pass data, known as parameters, into a function. A function can return data as a result.\n",
    "\n",
    "Lets try a simple example. We are going to make a function called 'square it' which squares any number that is passed to it. So if you pass it 3 it returns 9, etc.\n",
    "\n",
    "The function is formed like this:\n",
    "\n",
    "```python\n",
    "def square_it(input):    \n",
    "    result = input*input\n",
    "    return result\n",
    "```\n",
    "    \n",
    "The first line defines the function name (square_it) and specifies the parameter(s) (input). In this case we are only passing one parameter to the function.\n",
    "\n",
    "The instructions sit indented on the next line. Use tab or hit space four times.\n",
    "\n",
    "The final line instructs that result is returned.\n",
    "\n",
    "## Exercise 1.1 My first function\n",
    "\n",
    "Try and make the function below:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now to call the function we can try:\n",
    "\n",
    "```python\n",
    "square_it(3)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Or try giving the input and result names:\n",
    "\n",
    "```python\n",
    "input = 4\n",
    "result = square_it(input)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here, all the function is doing is taking 'input' and squaring it (4*4=16) and naming the result as result.\n",
    "\n",
    "You can call the input and result anything you like:\n",
    "\n",
    "```python\n",
    "eric = 5\n",
    "bananaman = square_it(eric)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exercise 1.2 Total footprint calculation function\n",
    "\n",
    "Make the following variables:\n",
    "```python\n",
    "Z_data = np.array([\n",
    "[660,10,2,30,1,1],\n",
    "[300,500,100,20,30,20],\n",
    "[200,400,300,10,30,100],\n",
    "[40,2,1,440,20,2],\n",
    "[20,200,200,140,400,90],\n",
    "[10,30,200,200,200,200]\n",
    "])\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```python\n",
    "Y_data = np.array([[690, 60], [380,20], [330, 15],[200, 580], [90, 200], [100, 280]])\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```python\n",
    "f_data = np.array([[980,1000,1200,1000,1100,1550]])\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```python\n",
    "sectors = ['Caladan Food',\n",
    "           'Caladan Machines',\n",
    "           'Caladan Energy',\n",
    "           'Arakis Food',\n",
    "           'Arakis Machines',\n",
    "           'Arakis Energy']\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```python\n",
    "final_demand = ['Caladan','Arakis']\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```python\n",
    "Z = pd.DataFrame(Z_data,index=sectors,columns=sectors)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```python\n",
    "Y = pd.DataFrame(Y_data,index=sectors,columns=final_demand)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```python\n",
    "f = pd.DataFrame(f_data,columns=sectors)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now take a look at this function\n",
    "\n",
    "```python\n",
    "def total_footprint_calc(Z,Y,y_region,f):    \n",
    "    x = np.sum(Z,1) + np.sum(Y,1)\n",
    "    big_X = np.tile(np.transpose(x),[6,1])\n",
    "    A = Z/big_X \n",
    "    L = np.linalg.inv(np.identity(6)-A)\n",
    "    e = f/np.transpose(x) \n",
    "    eL = np.dot(e,L)\n",
    "    footprint_by_region = np.dot(eL,y_region)\n",
    "\n",
    "    return footprint_by_region\n",
    "```\n",
    "The function ```total_footprint_calc``` has parameters ```Z```, ```Y```, ```y_region``` and ```f```. \n",
    "\n",
    "Notice that we have a function that takes in more than one parameter (in this case 4 parameters). \n",
    "\n",
    "Remember you can pass these parameters to the function under different names, but the order has to be the same as the order specified in the function.\n",
    "\n",
    "It returns ```footprint by region```.\n",
    "\n",
    "The calculations inside the function should be familiar to you from the previous exercise.\n",
    "\n",
    "Type or paste the function into the box below:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The only parameter we are missing is ```y_region```. \n",
    "\n",
    "We are going to first find the footprint of Caladan so make:\n",
    "\n",
    "```python\n",
    "y_caladan = Y['Caladan']\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "try\n",
    "\n",
    "```python\n",
    "Caladan_footprint = total_footprint_calc(Z,Y,y_caladan,f)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice that we have passed the parameter ```y_caladan``` to the function in the place of ```y_region```.\n",
    "\n",
    "What two lines of code can you write to calculate Arakis's footprint?\n",
    "\n",
    "*Hint* You will first need to make ```y_arakis```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Did you get the results 4443.62 and 2386.38 as before?\n",
    "\n",
    "## Exercise 1.3  Product footprint calculation function\n",
    "\n",
    "We are now going to make another function which is passed the exact same parameters but it returns the footprint by product.\n",
    "\n",
    "Make a new version of the function above.\n",
    "\n",
    "Name the function ```product_footprint_calc```\n",
    "\n",
    "Make the return ```footprint_by_product```\n",
    "\n",
    "Remove the line ```footprint_by_region = np.dot(eL,y_region)```\n",
    "\n",
    "and replace it with ```footprint_by_product = pd.DataFrame(np.dot(np.diagflat(eL),y_region),index=Z.index)```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Check that it works with:\n",
    "\n",
    "```python\n",
    "Caladan_footprint_by_product = product_footprint_calc(Z,Y,y_caladan,f)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exercise 1.4  Full footprint calculation function\n",
    "\n",
    "Now write a function that does the ```full_footprint_calc``` and returns ```full_footprint```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Try\n",
    "\n",
    "```python\n",
    "caladan_full_foot = full_footprint_calc(Z,Y,y_caladan,f)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. For loops\n",
    "\n",
    "## Exercise 2.1: Using for loops and a range (i)\n",
    "Imagine we want to get Python to print out the numbers from zero to ten.\n",
    "\n",
    "We could try writing:\n",
    "\n",
    "```python\n",
    "print(0)\n",
    "print(1)\n",
    "print(2)\n",
    "print(3)\n",
    "print(4)\n",
    "print(5)\n",
    "print(6)\n",
    "print(7)\n",
    "print(8)\n",
    "print(9)\n",
    "print(10)\n",
    "```\n",
    "\n",
    "but this is quite time consuming.\n",
    "\n",
    "Instead we can say if 'number' is in a set range print that number:\n",
    "\n",
    "```python\n",
    "for number in range(0,11):\n",
    "    print(number)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice that we have to tell Python to end the range at 11. One number after where we want to stop.\n",
    "\n",
    "## Exercise 2.2: Using for loops and a range (ii)\n",
    "\n",
    "Write the code to print out the numbers from five to fifteen"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exercise 2.3: Two methods for looping through years\n",
    "\n",
    "Try this code for printing out the years 1995-2009. Notice that we have changed the variable name to yr.\n",
    "\n",
    "```python\n",
    "for yr in range(1995,2010):\n",
    "    print(yr)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Another method would be to store the years in an array. This is useful if the data uses aperiodic years.\n",
    "\n",
    "Try:\n",
    "\n",
    "```python\n",
    "years = np.array([1995, 1997, 2000, 2005, 2007, 2008, 2009])\n",
    "for yr in years:\n",
    "    print(yr) \n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exercise 2.4: Looping through named variables in a list\n",
    "\n",
    "Try:\n",
    "```python\n",
    "zoo = np.array(['Alligator', 'Bear', 'Cheetah', 'Dog', 'Elephant', 'Flamingo', 'Giraffe'])\n",
    "for animal in zoo:\n",
    "    print(animal) \n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exercise 2.5: Nested for-loops\n",
    "\n",
    "Think back to this table of final demand in Dune.\n",
    "\n",
    "<img src=\"https://user-images.githubusercontent.com/24877051/146533767-fb43d903-3708-4174-9358-8c6e4ad76b52.png\" width=100 height=200 />\n",
    "\n",
    "Imagine we want to list this data in one long list that gives the Caladan 6 spends of final demand, then the Arakis 6 spends.\n",
    "\n",
    "We would need two loops. One loop says do Caladan then Arakis and another loop goes through each of the sectors.\n",
    "\n",
    "In Python we can write:\n",
    "\n",
    "```python\n",
    "for country in final_demand:\n",
    "    for product in sectors:\n",
    "        print (Y.loc[product,country])\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Check that you understand what is happening when we switch the first two lines and the result around.\n",
    "\n",
    "```python\n",
    "for product in sectors:\n",
    "    for country in final_demand:\n",
    "        print (Y.loc[product,country])\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Key learning points\n",
    "\n",
    "You should have learnt:\n",
    "\n",
    "<ol>\n",
    "<li>What the format of a function looks like (name, parameters, returns)</li>\n",
    "<li>How to write a function</li>\n",
    "<li>How to call a function with one or more parameters and return a result</li>\n",
    "<li>How to write for-loops using numerical ranges and items in a list</li>\n",
    "<li>How to write nested for-loops</li>\n",
    "   \n",
    "</ol>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
